package per.qiao.simplerest.core;

import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.ObjectUtils;
import per.qiao.simplerest.inteceptor.RestInteceptor;
import per.qiao.simplerest.proxy.RestServiceBeanFactory;
import per.qiao.simplerest.restresolver.DefaultRestMethodResolver;
import per.qiao.simplerest.restresolver.RestInvokerMethod;
import per.qiao.simplerest.restresolver.RestMethodResolver;
import per.qiao.simplerest.scanner.RestMappingScanner;
import per.qiao.simplerest.scanner.RestServiceScanner;
import per.qiao.simplerest.scanner.ServiceScanner;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * Company: 上海数惠系统技术有限公司
 * Department: 数据中心
 * Date: 2020-05-30 9:25
 *
 * @Author: qyp
 * Email: qiaoyp@dist.com.cn
 * Desc:
 */
public abstract class RestServiceSupport implements ImportBeanDefinitionRegistrar, EnvironmentAware, ResourceLoaderAware {

    /**
     * 类扫描器
     */
//    @Autowired
    private List<ServiceScanner> serviceScanners;

    private Environment environment;

    private ResourceLoader resourceLoader;

    /**
     * 方法解析器
     */
    private RestMethodResolver restMethodResolvers;

    /**
     * 拦截器
     */
    private List<RestInteceptor> restInteceptors;


    private Set<Class> restServiceSet = new LinkedHashSet<>();

    /**
     * 支持一个uri对应多个方法{@link per.qiao.simplerest.restenum.RestMethod RestMethod} 不同
     */
    public static final LinkedMultiValueMap<String, RestInvokerMethod> uriMethods = new LinkedMultiValueMap<>();

    public RestServiceSupport() {
        // 初始化两个默认的类扫描器
        serviceScanners = new ArrayList<>();
        // RestService接口扫描器
        RestServiceScanner restServiceScanner = new RestServiceScanner();
        // RestMapping注解接口扫描器
        RestMappingScanner restMappingScanner = new RestMappingScanner();
        serviceScanners.add(restServiceScanner);
        serviceScanners.add(restMappingScanner);

        registerServiceScanner(serviceScanners);
//        registerMethodResolvers(restMethodResolvers);
        // 扫描
        scannerService();

        // 解析方法
        restMethodResolvers = new DefaultRestMethodResolver();
        resolverMethod();
    }

    private void resolverMethod() {
        if (ObjectUtils.isEmpty(serviceScanners)) {
            return;
        }
        for (Class aClass : restServiceSet) {
            Method[] declaredMethods = aClass.getDeclaredMethods();
            for (Method method : declaredMethods) {
                RestInvokerMethod restInvokerMethod = restMethodResolvers.resolverMethod(method);
                String uri = restInvokerMethod.getUri();
                if (uriMethods.containsKey(uri)) {
                    uriMethods.get(uri).add(restInvokerMethod);
                } else {
                    ArrayList<RestInvokerMethod> arrayList = new ArrayList<>();
                    arrayList.add(restInvokerMethod);
                    uriMethods.put(uri, arrayList);
                }
            }
        }
    }


    protected void registerServiceScanner(List<ServiceScanner> serviceScanner) {
    }




    public void scannerService() {
        List<String> basepackages = getBasePackages();
        for (ServiceScanner serviceScanner : serviceScanners) {
            for (String servicePackage : basepackages) {
                Set<Class> scanner = serviceScanner.scanner(servicePackage);
                if (!ObjectUtils.isEmpty(scanner)) {
                    restServiceSet.addAll(scanner);
                }
            }
        }
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        if (ObjectUtils.isEmpty(restServiceSet)) {
            return;
        }
        for (Class beanClazz  : restServiceSet) {
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(beanClazz);
            GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
            definition.getConstructorArgumentValues().addGenericArgumentValue(beanClazz);
            definition.setBeanClass(RestServiceBeanFactory.class);
//            definition.setLazyInit(true);
            definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
            registry.registerBeanDefinition(beanClazz.getSimpleName(), definition);
        }
    }


    /**
     * 获取需要扫描的包路径
     *
     * @return
     */
    protected abstract List<String> getBasePackages();

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {

    }
}
